#include "StdAfx.h"
#include "Machine.h"
#include "Rom.h"

CMachine::CMachine()
{
int i;

for(i=0;i<MAX_CPUS;i++)
	CPU[i] = 0;
Watchdog = 0;
sNVRAM = 0;
}

CMachine::~CMachine()
{
int i;

if(Sound)
	Sound->SetCallback(0);
for(i=0;i<MAX_CPUS;i++)
	if(CPU[i])
		delete CPU[i];
if(Watchdog)
	delete Watchdog;
if(sNVRAM)
	delete sNVRAM;
}

void CMachine::ProcessInput()
{
InputPort *Port;
int n,i;
u32 t;

Input->Poll();
t = Input->Get();
for(n=0;n<MAX_INPUTPORTS;n++)
	{
	InputData[n] = 0;
	if((Port = RomSet->GetPort(n)) == 0)				//last input port?
		continue;
	for(i=0;i<8;i++)											//process each button press
		{
		InputButton *Button = &Port->Buttons[i];
		
		if(Button->Flags & I_HIGH)
			{
			if(Button->InputCode & t)				//button pressed?
				{
				InputData[n] |= Button->Bit;
				if(Button->Flags & I_NMI)			//needing nmi?
					CPU[Button->Flags >> 8]->NMI();
				if(Button->Flags & I_IRQ)			//needing irq?
					CPU[Button->Flags >> 8]->IRQ();
				}
			}
		else if(Button->Flags & I_LOW)
			{
			if((Button->InputCode & t) == 0)		//button not pressed?
				InputData[n] |= Button->Bit;
			else
				{
				if(Button->Flags & I_NMI)			//pressed and needing nmi?
					CPU[Button->Flags >> 8]->NMI();
				if(Button->Flags & I_IRQ)			//pressed and needing irq?
					CPU[Button->Flags >> 8]->IRQ();
				}
			}
		}
	}
t = Input->GetDip();
Dip[0] = (u8)t;
Dip[1] = (u8)(t >> 8);
Dip[2] = (u8)(t >> 16);
Dip[3] = (u8)(t >> 24);
}

// load romset into machine
int CMachine::Load(CRomSet *r)
{
RomSet = r;
return(0);
}

void CMachine::BlitRotate(u8 *S,u32 *D,u32 *P)
{
u32 Pitch;
int x,y;

if(RomSet == 0)
	return;
Pitch = Video->GetPitch() / 4;
switch(RomSet->GetRotate())
	{
	default:
		message("rotation not supported\n");
	case ROTATE_0:
		for(y=0;y<RomSet->ScreenH();y++)
			{
			for(x=0;x<RomSet->ScreenW();x++)
				D[x] = P[S[x]];
			D += Pitch;
			S += RomSet->ScreenW();
			}
		break;
	case ROTATE_90:
		for(y=0;y<RomSet->ScreenH();y++)
			{
			for(x=0;x<RomSet->ScreenW();x++)
				D[RomSet->ScreenW() - x] = P[S[x*RomSet->ScreenH()]];
			D += Pitch;
			S++;
			}
		break;
	case ROTATE_270:
		D += (RomSet->ScreenH() - 1) * Pitch;
		for(y=0;y<RomSet->ScreenH();y++)
			{
			for(x=0;x<RomSet->ScreenW();x++)
				D[x] = P[S[x*RomSet->ScreenH()]];
			D -= Pitch;
			S++;
			}
		break;
	}
}

void CMachine::BlitRotate16(u16 *S,u32 *D,u32 *P)
{
u32 Pitch;
int x,y;

if(RomSet == 0)
	return;
Pitch = Video->GetPitch() / 4;
switch(RomSet->GetRotate())
	{
	default:
		message("rotation not supported\n");
	case ROTATE_0:
		for(y=0;y<RomSet->ScreenH();y++)
			{
			for(x=0;x<RomSet->ScreenW();x++)
				D[x] = P[S[x]];
			D += Pitch;
			S += RomSet->ScreenW();
			}
		break;
	case ROTATE_90:
		for(y=0;y<RomSet->ScreenH();y++)
			{
			for(x=0;x<RomSet->ScreenW();x++)
				D[RomSet->ScreenW() - x] = P[S[x*RomSet->ScreenH()]];
			D += Pitch;
			S++;
			}
		break;
	case ROTATE_270:
		D += (RomSet->ScreenH() - 1) * Pitch;
		for(y=0;y<RomSet->ScreenH();y++)
			{
			for(x=0;x<RomSet->ScreenW();x++)
				D[x] = P[S[x*RomSet->ScreenH()]];
			D -= Pitch;
			S++;
			}
		break;
	}
}

void CMachine::LoadROMs()									//load roms into machine
{
int i,n,x;

for(n=RomSet->Num(),i=0;i<n;i++)
	{
	CRom *Rom = (CRom*)RomSet->GetROM(i);

	if(Rom->Data == 0)
		continue;
	for(x=0;x<LoadInfoList.num();x++)
		{
		LoadInfo *li = (LoadInfo*)LoadInfoList.get(x);

		if(Rom->Flags & li->Flags)
			{
			memcpy(li->Ptr + Rom->LoadAddr,Rom->Data,Rom->Size);
			break;
			}
		}
	}
}
